package com.swak.corpwx;

import java.util.concurrent.CompletableFuture;

import org.asynchttpclient.Response;
import org.asynchttpclient.request.body.multipart.ByteArrayPart;

import com.swak.Constants;
import com.swak.corpwx.department.CpDepartment;
import com.swak.corpwx.department.CpDepartmentAddResp;
import com.swak.corpwx.department.CpDepartmentDeleteResp;
import com.swak.corpwx.department.CpDepartmentGetResp;
import com.swak.corpwx.department.CpDepartmentListResp;
import com.swak.corpwx.department.CpDepartmentUpdateResp;
import com.swak.corpwx.kf.CpKfAccountAdd;
import com.swak.corpwx.kf.CpKfAccountAddResp;
import com.swak.corpwx.kf.CpKfAccountDel;
import com.swak.corpwx.kf.CpKfAccountDelResp;
import com.swak.corpwx.kf.CpKfAccountLink;
import com.swak.corpwx.kf.CpKfAccountLinkResp;
import com.swak.corpwx.kf.CpKfAccountUpdate;
import com.swak.corpwx.kf.CpKfAccountUpdateResp;
import com.swak.corpwx.kf.CpKfCustomerBatchGet;
import com.swak.corpwx.kf.CpKfCustomerBatchGetResp;
import com.swak.corpwx.kf.CpKfMsgList;
import com.swak.corpwx.kf.CpKfMsgListResp;
import com.swak.corpwx.kf.CpKfServiceStateGet;
import com.swak.corpwx.kf.CpKfServiceStateGetResp;
import com.swak.corpwx.kf.CpKfServiceStateTrans;
import com.swak.corpwx.kf.CpKfServiceStateTransResp;
import com.swak.corpwx.kf.CpKfServicerAdd;
import com.swak.corpwx.kf.CpKfServicerAddResp;
import com.swak.corpwx.kf.CpKfServicerDel;
import com.swak.corpwx.kf.CpKfServicerDelResp;
import com.swak.corpwx.kf.CpKfServicerStat;
import com.swak.corpwx.kf.CpKfServicerStatResp;
import com.swak.corpwx.media.CpMediaUpload;
import com.swak.corpwx.media.CpMediaUploadResp;
import com.swak.corpwx.user.CpUser;
import com.swak.corpwx.user.CpUserAddResp;
import com.swak.corpwx.user.CpUserGetIdResp;
import com.swak.corpwx.user.CpUserUpdateResp;
import com.swak.http.HttpService;
import com.swak.utils.JsonMapper;
import com.swak.wechat.WechatConfig;
import com.swak.wechat.token.AccessToken;

/**
 * 企业微信的基本服务
 * 
 * @author 618lf
 */
public abstract class AbstractCropwxService implements CpDepartmentService, CpMediaService, CpKfService, CpUserService,
		CpKfServicerService, CpKfCustomerService {

	/**
	 * Http 服务
	 *
	 * @return http 服务
	 */
	public abstract HttpService getHttpService();

	// ==========================================================
	// 调用 API 的token
	// ==========================================================

	/**
	 * 获取接入系统的 accessToken
	 *
	 * @param app app
	 * @return 异步结果
	 */
	public CompletableFuture<AccessToken> refreshAccessToken(WechatConfig app) {
		CompletableFuture<AccessToken> future = this.getHttpService().get()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/gettoken").addQueryParam("corpid", app.getSrcId())
				.addQueryParam("corpsecret", app.getSecret()).jsonResult(AccessToken.class).future();
		return future.thenApply(token -> {
			if (token != null) {
				token.setAddTime(System.currentTimeMillis());
			}
			return token;
		});
	}

	/**
	 * 上传图片
	 *
	 * @param app app
	 * @return 异步结果
	 */
	@Override
	public CompletableFuture<CpMediaUploadResp> upload(WechatConfig app, CpMediaUpload file) {
		ByteArrayPart part = new ByteArrayPart("media", file.getData(), "application/octet-stream",
				Constants.DEFAULT_ENCODING, file.getFileName());
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/media/upload")
				.addQueryParam("access_token", app.getAccessToken()).addQueryParam("type", file.getType())
				// .addQueryParam("debug", "1")
				.addBodyPart(part).plainResult().future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpMediaUploadResp.class);
			}
			return new CpMediaUploadResp();
		});
	}

	// ==========================================================
	// 部门相关实现
	// ==========================================================

	@Override
	public CompletableFuture<CpDepartmentAddResp> addDepartment(WechatConfig app, CpDepartment add) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/department/create")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(add)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpDepartmentAddResp.class);
			}
			return new CpDepartmentAddResp();
		});
	}

	@Override
	public CompletableFuture<CpDepartmentUpdateResp> updateDepartment(WechatConfig app, CpDepartment update) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/department/update")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(update)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpDepartmentUpdateResp.class);
			}
			return new CpDepartmentUpdateResp();
		});
	}

	@Override
	public CompletableFuture<CpDepartmentDeleteResp> delDepartment(WechatConfig app, CpDepartment del) {
		return null;
	}

	@Override
	public CompletableFuture<CpDepartmentGetResp> getDepartment(WechatConfig app, Integer id) {
		CompletableFuture<Response> future = this.getHttpService().get()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/department/get")
				.addQueryParam("access_token", app.getAccessToken()).addQueryParam("id", id.toString()).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpDepartmentGetResp.class);
			}
			return new CpDepartmentGetResp();
		});
	}

	@Override
	public CompletableFuture<CpDepartmentListResp> listDepartments(WechatConfig app, Integer id) {
		CompletableFuture<Response> future = this.getHttpService().get()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/department/simplelist")
				.addQueryParam("access_token", app.getAccessToken()).addQueryParam("id", id.toString()).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpDepartmentListResp.class);
			}
			return new CpDepartmentListResp();
		});
	}

	// ==========================================================
	// 客服相关实现
	// ==========================================================

	@Override
	public CompletableFuture<CpKfAccountAddResp> addAccount(WechatConfig app, CpKfAccountAdd add) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/account/add")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(add)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfAccountAddResp.class);
			}
			return new CpKfAccountAddResp();
		});
	}

	@Override
	public CompletableFuture<CpKfAccountUpdateResp> updateAccount(WechatConfig app, CpKfAccountUpdate update) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/account/update")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(update)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfAccountUpdateResp.class);
			}
			return new CpKfAccountUpdateResp();
		});
	}

	@Override
	public CompletableFuture<CpKfAccountDelResp> delAccount(WechatConfig app, CpKfAccountDel del) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/account/del")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(del)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfAccountDelResp.class);
			}
			return new CpKfAccountDelResp();
		});
	}

	@Override
	public CompletableFuture<CpKfAccountLinkResp> accountLink(WechatConfig app, CpKfAccountLink link) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/add_contact_way")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(link)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfAccountLinkResp.class);
			}
			return new CpKfAccountLinkResp();
		});
	}

	@Override
	public CompletableFuture<CpKfServicerAddResp> addServicer(WechatConfig app, CpKfServicerAdd add) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/servicer/add")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(add)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfServicerAddResp.class);
			}
			return new CpKfServicerAddResp();
		});
	}

	@Override
	public CompletableFuture<CpKfServicerDelResp> deleteServicer(WechatConfig app, CpKfServicerDel delete) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/servicer/del")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(delete)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfServicerDelResp.class);
			}
			return new CpKfServicerDelResp();
		});
	}

	@Override
	public CompletableFuture<CpKfServiceStateTransResp> transServiceState(WechatConfig app,
			CpKfServiceStateTrans trans) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/service_state/trans")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(trans)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfServiceStateTransResp.class);
			}
			return new CpKfServiceStateTransResp();
		});
	}

	@Override
	public CompletableFuture<CpKfServiceStateGetResp> getServiceState(WechatConfig app, CpKfServiceStateGet get) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/service_state/get")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(get)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfServiceStateGetResp.class);
			}
			return new CpKfServiceStateGetResp();
		});
	}

	@Override
	public CompletableFuture<CpKfMsgListResp> syncMsg(WechatConfig app, CpKfMsgList query) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/sync_msg")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(query)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfMsgListResp.class);
			}
			return new CpKfMsgListResp();
		});
	}

	@Override
	public CompletableFuture<CpKfCustomerBatchGetResp> batchget(WechatConfig app, CpKfCustomerBatchGet get) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/customer/batchget")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(get)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfCustomerBatchGetResp.class);
			}
			return new CpKfCustomerBatchGetResp();
		});
	}
	
	@Override
	public CompletableFuture<CpKfServicerStatResp> statServicer(WechatConfig app, CpKfServicerStat stat) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/kf/get_servicer_statistic")
				.addQueryParam("access_token", app.getAccessToken())
				.addQueryParam("debug", "1")
				.setBody(JsonMapper.toJson(stat)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpKfServicerStatResp.class);
			}
			return new CpKfServicerStatResp();
		});
	}

	// ==========================================================
	// 用戶相关实现
	// ==========================================================

	@Override
	public CompletableFuture<CpUserAddResp> addUser(WechatConfig app, CpUser add) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/user/create")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(add)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpUserAddResp.class);
			}
			return new CpUserAddResp();
		});
	}

	@Override
	public CompletableFuture<CpUserUpdateResp> updateUser(WechatConfig app, CpUser update) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/user/update")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(update)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpUserUpdateResp.class);
			}
			return new CpUserUpdateResp();
		});
	}

	@Override
	public CompletableFuture<CpUserGetIdResp> getUserId(WechatConfig app, CpUser mobile) {
		CompletableFuture<Response> future = this.getHttpService().post()
				.setUrl("https://qyapi.weixin.qq.com/cgi-bin/user/getuserid")
				.addQueryParam("access_token", app.getAccessToken()).setBody(JsonMapper.toJson(mobile)).plainResult()
				.future();
		return future.thenApply(res -> {
			if (res.getStatusCode() == 200) {
				String body = res.getResponseBody();
				return JsonMapper.fromJson(body, CpUserGetIdResp.class);
			}
			return new CpUserGetIdResp();
		});
	}
}